﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace EasyTrader.Signal
{
    using PriceSignalList = List<PriceSignal>;
    using PricePointList = List<EasyTrader.Wave.PricePoint>;
    using PriceWaveList = List<EasyTrader.Wave.PriceWave>;
    public class WaveSignalManager : EasyTrader.Signal.SignalManager
    {
        private EasyTrader.Signal.HighLowInfo m_CurHighLowInfo = new EasyTrader.Signal.HighLowInfo();
        public EasyTrader.Signal.HighLowInfo CurHighLowInfo
        {
            get { return m_CurHighLowInfo; }
            set { m_CurHighLowInfo = value; }
        }

        public WaveSignalManager()
        {
            // 여기서 데이터 셋을 넣어 준다.
            m_EasyTraderWaveManager.EasyTraderDataSet = GlobalVar.GDataSet;
        }

        private EasyTrader.Signal.ForecastingInfo m_ForeInfo = new EasyTrader.Signal.ForecastingInfo();
        public EasyTrader.Signal.ForecastingInfo ForeInfo
        {
            get { return m_ForeInfo; }
            set { m_ForeInfo = value; }
        }
        private PricePointList m_PriceList = null;
        private PriceWaveList m_SignalWaveList = new PriceWaveList();
        public PriceWaveList SignalWaveList
        {
            get { return m_SignalWaveList; }
            set { m_SignalWaveList = value; }
        }

        // 이 신호 파동은 현재의 기준파의 정보를 담고 있다.
        private EasyTrader.Wave.PriceWave m_SignalWave = new EasyTrader.Wave.PriceWave();
        public EasyTrader.Wave.PriceWave SignalWave
        {
            get { return m_SignalWave; }
            set { m_SignalWave = value; }
        }

        private EasyTrader.Wave.WaveManager m_EasyTraderWaveManager = new EasyTrader.Wave.WaveManager();
        public EasyTrader.Wave.WaveManager EasyTraderWaveManager
        {
            get { return m_EasyTraderWaveManager; }
            set { m_EasyTraderWaveManager = value; }
        }

        private PricePointList m_ForePriceList = new PricePointList();
        public PricePointList ForePriceList
        {
            get { return m_ForePriceList; }
            set { m_ForePriceList = value; }
        }

        public EasyTrader.Wave.PriceWave FindSignalWave()
        {
            if (m_EasyTraderWaveManager == null)
                return null;
            return FindSignalWave(m_EasyTraderWaveManager.ArragedWaveList);
        }

        public int GetArrangedWaveCount()
        {
            if (m_EasyTraderWaveManager == null)
                return 0;
            return m_EasyTraderWaveManager.ArragedWaveList.Count;
        }

        // 이 함수는 기준파의 높이에 미치지 못하는 파동의 개수를 찾아내 반환한다.
        public int GetShortWaveCount()
        {
            if (m_EasyTraderWaveManager == null)
                return 0;

            PriceWaveList waveList = m_EasyTraderWaveManager.ArragedWaveList;
            int waveCount = waveList.Count;
            if (waveCount == 0)
                return 0;
            int shortWaveCount = 0;
            for (int i = waveCount -1; i >= 0; i--)
            {
                EasyTrader.Wave.PriceWave wave = waveList[i];
                if (wave.Height() < GlobalVar.SignalWaveHeight)
                    shortWaveCount++;
                else
                    break;
            }

            return shortWaveCount;
        }

        // 이함수는 현재 위치에서 진폭의 상부, 중부, 하부 중 어느 위치에 있는지 알려준다.
        public int FindHighLowPos(int a_CurIndex)
        {
            EasyTrader.DataSet.FutOptChartTable curTable = m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return GlobalVar.PosNone;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return GlobalVar.PosNone;

            int startX = Math.Min(a_CurIndex, rowCount - 1);
            if (startX < 0)
                startX = 0;
            if (startX > rowCount - 1)
                startX = rowCount - 1;

            DataRow row = curTable.Rows[startX];
            double close = Convert.ToDouble(row["종가"]);
            double dayHigh = 0.0, dayLow = 0.0;
            if (GetDayHighLow(a_CurIndex, ref dayHigh, ref dayLow) < 0)
                return GlobalVar.PosNone;
            double dayAmp = dayHigh - dayLow;
            double highLimit = dayHigh - GlobalVar.HighLowRange;
            double lowLimit = dayLow + GlobalVar.HighLowRange;
            if (close >= highLimit)
                return GlobalVar.PosHigh;
            if (close <= lowLimit)
                return GlobalVar.PosLow;

            return GlobalVar.PosMid;
        }


        public int MakeIndexWaveInfo(int a_CurIndex, EasyTrader.Wave.PriceWave a_IndexWave, int a_HighLowIndex, double a_HighLowVal)
        {
            EasyTrader.DataSet.FutOptChartTable curTable = m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return -1;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return -1;

            int startX = Math.Min(a_CurIndex, rowCount - 1);
            if (startX < 0)
                startX = 0;
            if (startX > rowCount - 1)
                startX = rowCount - 1;

            DataRow row = curTable.Rows[startX];
            double close = Convert.ToDouble(row["종가"]);

            a_IndexWave.StartX = a_HighLowIndex;
            a_IndexWave.StartY = a_HighLowVal;
            a_IndexWave.EndX = a_CurIndex;
            a_IndexWave.EndY = close;

            double deltaY = a_IndexWave.EndY - a_IndexWave.StartY;
            if (deltaY > 0)
                a_IndexWave.Slope = GlobalVar.PriceUp;
            else if (deltaY < 0)
                a_IndexWave.Slope = GlobalVar.PriceDown;
            else
                a_IndexWave.Slope = GlobalVar.PriceFlat;

            return 1;
        }

        public double GetIndexWaveHighLowRange(int a_CurIndex, int a_HighLowIndex)
        {
            EasyTrader.DataSet.FutOptChartTable curTable = m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return -1.0;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return -1.0;

            int startX = Math.Min(a_CurIndex, rowCount - 1);
            if (startX < 0)
                startX = 0;
            if (startX > rowCount - 1)
                startX = rowCount - 1;
            int endX = Math.Max(0, a_HighLowIndex);
            double high = -99999.0;
            double low = 9999.0;
            for (int i = 0; i <= a_CurIndex; i++)
            {
                DataRow row = curTable.Rows[i];
                double close = Convert.ToDouble(row["종가"]);
                if (high > close)
                    high = close;
                if (low < close)
                    low = close;
            }

            return Math.Abs(high - low);
        }

        public int FindPeakIndex(int a_CurIndex, EasyTrader.Signal.HighLowInfo a_HighLowInfo, ref int a_HighLowIndex, ref double a_HighLowVal, ref int a_Trend)
        {
            EasyTrader.DataSet.FutOptChartTable curTable = m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return -1;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return -1;

            int startX = Math.Min(a_CurIndex, rowCount - 1);
            if (startX < 0)
                startX = 0;
            if (startX > rowCount - 1)
                startX = rowCount - 1;

            DataRow row = curTable.Rows[startX];
            double close = Convert.ToDouble(row["종가"]);
            double dayHigh = 0.0, dayLow = 0.0;
            if (GetDayHighLow(startX, ref dayHigh, ref dayLow) < 0)
                return -1;
            double dayAmp = dayHigh - dayLow;
            double highLimit = a_HighLowInfo.CloseMax - GlobalVar.HighLowRange;
            double lowLimit = a_HighLowInfo.CloseMin + GlobalVar.HighLowRange;
            int curHighLowPos = GlobalVar.PosMid;
            if (close >= highLimit)
                curHighLowPos = GlobalVar.PosHigh;
            if (close <= lowLimit)
                curHighLowPos = GlobalVar.PosLow;
            int oldHighLowPos = curHighLowPos;
            int changeTrendCount = 1;
            a_Trend = GlobalVar.TrendNone;
            for (int i = startX; i >= 0; i--)
            {
                row = curTable.Rows[i];
                close = Convert.ToDouble(row["종가"]);
                curHighLowPos = GlobalVar.PosMid;
                if (close >= highLimit)
                    curHighLowPos = GlobalVar.PosHigh;
                if (close <= lowLimit)
                    curHighLowPos = GlobalVar.PosLow;
                if (curHighLowPos != oldHighLowPos)
                {
                    changeTrendCount++;
                    if (changeTrendCount == 2)
                    {
                        if (oldHighLowPos == GlobalVar.PosMid)
                        {
                            if (curHighLowPos == GlobalVar.PosHigh)
                            {
                                a_Trend = GlobalVar.HighToMid;
                                a_HighLowIndex = a_HighLowInfo.CloseMaxX;
                                a_HighLowVal = a_HighLowInfo.CloseMax;
                            }
                            else if (curHighLowPos == GlobalVar.PosLow)
                            {
                                a_Trend = GlobalVar.LowToMid;
                                a_HighLowIndex = a_HighLowInfo.CloseMinX;
                                a_HighLowVal = a_HighLowInfo.CloseMin;
                            }
                        }
                        else if (oldHighLowPos == GlobalVar.PosHigh)
                        {
                            if (curHighLowPos == GlobalVar.PosMid)
                            {
                                a_Trend = GlobalVar.MidToHigh;
                                a_HighLowIndex = a_HighLowInfo.CloseMinX;
                                a_HighLowVal = a_HighLowInfo.CloseMin;
                            }
                            else if (curHighLowPos == GlobalVar.PosLow)
                            {
                                a_Trend = GlobalVar.LowToHigh;
                                a_HighLowIndex = a_HighLowInfo.CloseMinX;
                                a_HighLowVal = a_HighLowInfo.CloseMin;
                            }
                        }
                        else if (oldHighLowPos == GlobalVar.PosLow)
                        {
                            if (curHighLowPos == GlobalVar.PosMid)
                            {
                                a_Trend = GlobalVar.MidToLow;
                                a_HighLowIndex = a_HighLowInfo.CloseMaxX;
                                a_HighLowVal = a_HighLowInfo.CloseMax;
                            }
                            else if (curHighLowPos == GlobalVar.PosHigh)
                            {
                                a_Trend = GlobalVar.HighToLow;
                                a_HighLowIndex = a_HighLowInfo.CloseMaxX;
                                a_HighLowVal = a_HighLowInfo.CloseMax;
                            }
                        }
                        break;
                    }
                    oldHighLowPos = curHighLowPos;
                }
            }

            return 1;
        }


        public int FindFirstHighVal(int a_CurIndex, EasyTrader.Signal.HighLowInfo a_HighLowInfo, ref int a_HighIndex, ref double a_HighVal)
        {
            EasyTrader.DataSet.FutOptChartTable curTable = m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return -1;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return -1;

            int startX = Math.Min(a_CurIndex, rowCount - 1);
            if (startX < 0)
                startX = 0;
            if (startX > rowCount - 1)
                startX = rowCount - 1;
            for (double j = 0.0; j < 4.0; j = j + 1.0)
            {
                double highLimit = a_HighLowInfo.CloseMax - j * 0.05;
                for (int i = startX; i >= 0; i--)
                {
                    DataRow row = curTable.Rows[i];
                    double close = Convert.ToDouble(row["종가"]);
                    if (close > highLimit)
                    {
                        a_HighIndex = i;
                        a_HighVal = a_HighLowInfo.CloseMax;
                        break;
                    }
                }
            }

            return 1;
        }

        public int FindFirstLowVal(int a_CurIndex, EasyTrader.Signal.HighLowInfo a_HighLowInfo, ref int a_LowIndex, ref double a_LowVal)
        {
            EasyTrader.DataSet.FutOptChartTable curTable = m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return -1;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return -1;

            int startX = Math.Min(a_CurIndex, rowCount - 1);
            if (startX < 0)
                startX = 0;
            if (startX > rowCount - 1)
                startX = rowCount - 1;
            for (double j = 0.0; j < 4.0; j = j + 1.0)
            {
                double lowLimit = a_HighLowInfo.CloseMin + j * 0.05;
                for (int i = startX; i >= 0; i--)
                {
                    DataRow row = curTable.Rows[i];
                    double close = Convert.ToDouble(row["종가"]);
                    if (close < lowLimit)
                    {
                        a_LowIndex = i;
                        a_LowVal = a_HighLowInfo.CloseMin;
                        break;
                    }
                }
            }
            return 1;
        }


        public int GetDayHighLow(int a_CurIndex, ref double a_DayHigh, ref double a_DayLow)
        {
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetFutOptChartTable();

            if (curTable == null)
                return -1;
            int rowCount = curTable.Rows.Count;
            if (rowCount == 0)
                return -1;
            if (a_CurIndex > rowCount - 1)
                a_CurIndex = rowCount - 1;
            double high = 0;
            double low = 0;
            a_DayHigh = -10000.0;
            a_DayLow = 10000.0;
            DataRow row = null;
            for (int i = 0; i <= a_CurIndex; i++)
            {
                row = curTable.Rows[i];
                high = Convert.ToDouble(row["고가"]);
                low = Convert.ToDouble(row["저가"]);
                if (high > a_DayHigh)
                    a_DayHigh = high;
                if (low < a_DayLow)
                    a_DayLow = low;
            }

            return 1;
        }

        public double GetDayAmp(int a_CurIndex)
        {
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetFutOptChartTable();

            if (curTable == null)
                return 0.0;
            int rowCount = curTable.Rows.Count;
            if (rowCount == 0)
                return 0.0;
            if (a_CurIndex > rowCount - 1)
                a_CurIndex = rowCount - 1;
            double high = 0;
            double low = 0;
            double a_DayHigh = -10000.0;
            double a_DayLow = 10000.0;
            DataRow row = null;
            for (int i = 0; i <= a_CurIndex; i++)
            {
                row = curTable.Rows[i];
                high = Convert.ToDouble(row["고가"]);
                low = Convert.ToDouble(row["저가"]);
                if (high > a_DayHigh)
                    a_DayHigh = high;
                if (low < a_DayLow)
                    a_DayLow = low;
            }


            return Math.Abs(a_DayHigh - a_DayLow);
        }

        public double GetDayCloseAmp(int a_CurIndex)
        {
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetFutOptChartTable();

            if (curTable == null)
                return 0.0;
            int rowCount = curTable.Rows.Count;
            if (rowCount == 0)
                return 0.0;
            if (a_CurIndex > rowCount - 1)
                a_CurIndex = rowCount - 1;
            double close = 0.0;
            double a_DayHigh = -10000.0;
            double a_DayLow = 10000.0;
            DataRow row = null;
            for (int i = 0; i <= a_CurIndex; i++)
            {
                row = curTable.Rows[i];
                close = Convert.ToDouble(row["종가"]);
                if (close > a_DayHigh)
                    a_DayHigh = close;
                if (close < a_DayLow)
                    a_DayLow = close;
            }


            return Math.Abs(a_DayHigh - a_DayLow);
        }

        // 이 함수는 가장 최근의 파동에서 시작하여 기준 높이 이상이 되는 마지막 파동을 찾는다.
        // 기준 높이는 1.1 포인트이다. 이것은 고가와 저가를 기준으로 찾는다.
        // 파동은 어디까지 조사할 것인지를 지시한다. 현재 파동의 10분이전까지 조사해 보고 없으면
        // 다음 파동의 10분전까지 조사하는 방식으로 진행을 한다.
        // 반환되는 파동속에 이 구간의 고점과 저점이 들어간다.
        // 기준파는 현재파를 포함할 수 없다. 단 파동이 하나일 때는 그게 기준파가 된다.
        private EasyTrader.Wave.PriceWave FindSignalWave(PriceWaveList a_WaveList)
        {
            if (a_WaveList == null || m_EasyTraderDataSet == null)
                return null;
            int count = a_WaveList.Count;
            if (count == 0)
                return null;
            EasyTrader.DataSet.FutOptChartTable curTable = m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return null;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return null;

            EasyTrader.Wave.PriceWave signalWave = null;
            EasyTrader.Wave.PriceWave lastWave = a_WaveList[count - 1];
            // 현재 파동이 기준파의 기준에 부합할 때는 바로 반환한다.
            if (lastWave.Height() > GlobalVar.SignalWaveHeight)
            {
                signalWave = new EasyTrader.Wave.PriceWave();
                signalWave.StartX = lastWave.StartX;
                signalWave.EndX = lastWave.EndX;
                signalWave.StartY = lastWave.StartY;
                signalWave.EndY = lastWave.EndY;
                signalWave.Slope = lastWave.Slope;
                return signalWave;
            }
            int waveStartIndex = count - 2;
            if (waveStartIndex < 0)
                waveStartIndex = 0;

            EasyTrader.Wave.PriceWave wave = a_WaveList[waveStartIndex];
            int startX = wave.EndX;
            if (startX > rowCount - 1)
                startX = rowCount - 1;
            DataRow row = curTable.Rows[startX];
            double high = Convert.ToDouble(row["고가"]);
            double low = Convert.ToDouble(row["저가"]);
            //signalWave.StartX = startX;
            //signalWave.EndX = startX;
            //signalWave.StartY = low;
            //signalWave.EndY = high;
            double highY = high;
            double lowY = low;
            int highX = startX;
            int lowX = startX;
            double deltaY = 0;
            for (int i = waveStartIndex; i >= 0; i--)
            {
                wave = a_WaveList[i];
                int endX = wave.StartX;
                endX = Math.Max(wave.StartX - 10, 0);
                for (int j = startX; j >= endX; j--)
                {
                    row = curTable.Rows[j];
                    high = Convert.ToDouble(row["고가"]);
                    low = Convert.ToDouble(row["저가"]);
                    if (low < lowY)
                    {
                        lowY = low;
                        lowX = j;
                    }
                    if (high > highY)
                    {
                        highY = high;
                        highX = j;
                    }
                }
                deltaY = Math.Abs(highY - lowY);
                if (deltaY >= GlobalVar.SignalWaveHeight)
                {
                    signalWave = new EasyTrader.Wave.PriceWave();
                    signalWave.StartX = highX;
                    signalWave.StartY = highY;
                    signalWave.EndX = lowX;
                    signalWave.EndY = lowY;
                    signalWave.Slope = GlobalVar.PriceFlat;
                    return signalWave;
                }
                startX = endX;
            }

            // 여기까지 왔다면 기준에 맞는 기준파가 없는 것이다.
            // 짧은 기준파만 존재하는 것이다. 따라서 기준파 최소길이를 확인한다.
            if (deltaY >= GlobalVar.MinSignalWaveHeight)
            {
                signalWave = new EasyTrader.Wave.PriceWave();
                signalWave.StartX = highX;
                signalWave.StartY = highY;
                signalWave.EndX = lowX;
                signalWave.EndY = lowY;
                signalWave.Slope = GlobalVar.PriceFlat;
                return signalWave;
            }
            else
                return null;
        }

        // 이 함수는 파동의 고점저점을 구한다. 이때 고가와 저가, 종가에 대하여 각각 구한다.
        public void FindWaveHighLow(EasyTrader.Wave.PriceWave a_Wave)
        {
            if (a_Wave == null || m_EasyTraderDataSet == null)
                return;

            EasyTrader.DataSet.FutOptChartTable curTable = m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return;

            int startX = a_Wave.StartX;
            startX = Math.Max(0, startX);
            int endX = Math.Min(a_Wave.EndX, curTable.GetRowCount() - 1);
            DataRow row = curTable.Rows[startX];
            double high = Convert.ToDouble(row["고가"]);
            double low = Convert.ToDouble(row["저가"]);
            double close = Convert.ToDouble(row["종가"]);
            a_Wave.HighY = -1000; // high;
            a_Wave.HighX = startX;
            a_Wave.LowY = 1000;// low;
            a_Wave.LowX = startX;
            a_Wave.CloseMax = -1000;// close;
            a_Wave.CloseMaxX = startX;
            a_Wave.CloseMin = 1000; // close;
            a_Wave.CloseMinX = startX;
            for (int j = startX; j <= endX; j++)
            {
                row = curTable.Rows[j];
                high = Convert.ToDouble(row["고가"]);
                low = Convert.ToDouble(row["저가"]);
                close = Convert.ToDouble(row["종가"]);
                if (high != 0 && high > a_Wave.HighY)
                {
                    a_Wave.HighY = high;
                    a_Wave.HighX = j;
                }
                if (low != 0 && low < a_Wave.LowY)
                {
                    a_Wave.LowY = low;
                    a_Wave.LowX = j;
                }
                if (close != 0 && close < a_Wave.CloseMin)
                {
                    a_Wave.CloseMin = close;
                    a_Wave.CloseMinX = j;
                }
                if (close != 0 && close > a_Wave.CloseMax)
                {
                    a_Wave.CloseMax = close;
                    a_Wave.CloseMaxX = j;
                }
            }
                
        }

        public EasyTrader.Signal.HighLowInfo FindSignalHeightInfo(int a_CurIndex)
        {
            PriceWaveList a_WaveList = m_EasyTraderWaveManager.ArragedWaveList;

            if (a_WaveList == null || m_EasyTraderDataSet == null)
                return m_CurHighLowInfo;
            int count = a_WaveList.Count;
            if (count == 0)
                return m_CurHighLowInfo;
            EasyTrader.DataSet.FutOptChartTable curTable = m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return m_CurHighLowInfo;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return m_CurHighLowInfo;

            int waveStartIndex = count - 1;

            //EasyTrader.Signal.HighLowInfo highLowInfo = new EasyTrader.Signal.HighLowInfo();
            EasyTrader.Wave.PriceWave wave = a_WaveList[waveStartIndex];
            int startX = Math.Min(a_CurIndex, rowCount - 1);
            if (startX < 0)
                startX = 0;
            if (startX > rowCount - 1)
                startX = rowCount - 1;

            DataRow row = curTable.Rows[startX];
            m_CurHighLowInfo.HighY = -10000; //Convert.ToDouble(row["고가"]);
            m_CurHighLowInfo.LowY = 10000; // Convert.ToDouble(row["저가"]);
            m_CurHighLowInfo.CloseMin = 10000; // Convert.ToDouble(row["종가"]);
            m_CurHighLowInfo.CloseMax = -10000;// Convert.ToDouble(row["종가"]);
            double high = 0.0, low = 0.0, close = 0.0;
            double deltaY = 0.0;
            for (int i = waveStartIndex; i >= 0; i--)
            {
                wave = a_WaveList[i];
                int endX = wave.StartX;
                endX = Math.Max(wave.StartX, 0);
                for (int j = startX; j >= endX; j--)
                {
                    row = curTable.Rows[j];
                    high = Convert.ToDouble(row["고가"]);
                    low = Convert.ToDouble(row["저가"]);
                    close = Convert.ToDouble(row["종가"]);
                    if (low != 0 && low < m_CurHighLowInfo.LowY)
                    {
                        m_CurHighLowInfo.LowY = low;
                        m_CurHighLowInfo.LowX = j;
                    }
                    if (high != 0 && high > m_CurHighLowInfo.HighY)
                    {
                        m_CurHighLowInfo.HighY = high;
                        m_CurHighLowInfo.HighX = j;
                    }
                    if (close != 0 && close < m_CurHighLowInfo.CloseMin)
                    {
                        m_CurHighLowInfo.CloseMin = close;
                        m_CurHighLowInfo.CloseMinX = j;
                    }
                    if (close != 0 && close > m_CurHighLowInfo.CloseMax)
                    {
                        m_CurHighLowInfo.CloseMax = close;
                        m_CurHighLowInfo.CloseMaxX = j;
                    }
                }
                deltaY = Math.Abs(m_CurHighLowInfo.CloseMax - m_CurHighLowInfo.CloseMin);
                if (deltaY >= GlobalVar.MaxCloseHeight)
                {
                    return m_CurHighLowInfo;
                }
                startX = endX;
            }

            return m_CurHighLowInfo;
        }

        public bool MakeForecastingPriceList(int a_DataCount, string a_RegType, int a_ReferenceRange)
        {
            if (a_DataCount <= 2)
                return false;
            // 우선 출력 포인트 목록을 비워준다.
            m_ForePriceList.Clear();
            EasyTrader.DataSet.FutOptChartTable curTable = m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return false;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return false;
            if (rowCount < a_DataCount)
                return false;

            DataRow row = curTable.Rows[0];
            double openVal = Convert.ToDouble(row["시가"]);
            EasyTrader.Wave.PricePoint point = new EasyTrader.Wave.PricePoint();
            point.X = 0;
            point.Y = openVal;
            point.Time = 900;
            m_ForePriceList.Add(point);
            for (int i = 0; i < a_DataCount; i++)
            {
                row = curTable.Rows[i];
                double Y = m_Forecaster.GetForecastingY(curTable, "종가", "Linear", i, 10, openVal);
                if (Y == 0)
                {
                    Y = Convert.ToDouble(row["종가"]);
                }

                point = new EasyTrader.Wave.PricePoint();
                point.X = i + 1;
                point.Y = Y;
                point.Time = Convert.ToDouble(row["시각"]);
                m_ForePriceList.Add(point);
            }

            return true;
        }


        public bool MakeForecastingPriceList(string a_RegType, int a_ReferenceRange)
        {
            // 우선 출력 포인트 목록을 비워준다.
            m_ForePriceList.Clear();
            EasyTrader.DataSet.FutOptChartTable curTable = m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return false;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return false;

            DataRow row = curTable.Rows[0];
            double openVal = Convert.ToDouble(row["시가"]);
            EasyTrader.Wave.PricePoint point = new EasyTrader.Wave.PricePoint();
            point.X = 0;
            point.Y = openVal;
            point.Time = 900;
            m_ForePriceList.Add(point);
            for (int i = 0; i < rowCount; i++)
            {
                row = curTable.Rows[i];
                double Y = m_Forecaster.GetForecastingY(curTable, "종가", a_RegType, i, a_ReferenceRange, openVal);
                if (Y == 0)
                {
                    Y = Convert.ToDouble(row["종가"]);
                }

                point = new EasyTrader.Wave.PricePoint();
                point.X = i + 1;
                point.Y = Y;
                point.Time = Convert.ToDouble(row["시각"]);
                m_ForePriceList.Add(point);
            }
            return true;
        }

        public ForecastingInfo GetForecastingInfo(string a_ColName, string a_RegType, int a_MaxRange)
        {
            if (a_ColName == "")
                return null;
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return null;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return null;
            return Forecaster.GetForecastingInfo(curTable, a_ColName, a_RegType, a_MaxRange);
        }

        public ForecastingInfo GetForecastingInfoWithOpen(string a_ColName, string a_RegType, int a_MaxRange)
        {
            if (a_ColName == "")
                return null;
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return null;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return null;
            DataRow row = curTable.Rows[0];
            double openVal = Convert.ToDouble(row["시가"]);
            return Forecaster.GetForecastingInfoWithOpen(curTable, a_ColName, a_RegType, a_MaxRange, openVal);
        }

        public ForecastingInfo GetForecastingInfo(string a_ColName, string a_RegType, int a_EndX, int a_MaxRange, bool a_AllowZero)
        {
            if (a_ColName == "" || a_EndX < 0 || a_MaxRange < 0)
                return null;
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return null;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return null;
            return Forecaster.GetForecastingInfo(curTable, a_ColName, a_RegType, a_EndX, a_MaxRange, a_AllowZero);
        }

        public ForecastingInfo GetForecastingInfoWithOpen(string a_ColName, string a_RegType, int a_EndX, int a_MaxRange)
        {
            if (a_ColName == "" || a_EndX < 0 || a_MaxRange < 0)
                return null;
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return null;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return null;
            int startX = GetStartX(a_EndX, a_MaxRange);
            DataRow row = curTable.Rows[startX];
            double openVal = Convert.ToDouble(row["시가"]);
            return Forecaster.GetForecastingInfo(curTable, a_ColName, a_RegType, a_EndX, a_MaxRange, openVal);
        }

        // 이 함수는 예측지수에 의해서 매도와 매수를 결정해 반환한다.
        // 퍼센트로 반환을 한다.
        public double GetForecastingSignal(int a_CurIndex)
        {
            double signalVal = GlobalVar.SignalNone;

            GetForecastingInfo(m_ForeInfo, "종가", GlobalVar.RegressionType, a_CurIndex, GlobalVar.PriceReferenceRange, false);
            if (m_ForeInfo.StartX == -1 || m_ForeInfo.EndX == -1)
                return signalVal;

            double deltaY = m_ForeInfo.EndY - m_ForeInfo.StartY;

            double deltaX = m_ForeInfo.EndX - m_ForeInfo.StartX;
            double ABSdeltaY = Math.Abs(deltaY) * GlobalVar.PricePerMin;
            double ABSdeltaX = Math.Abs(deltaX);
            double radians = Math.Atan2(ABSdeltaY, ABSdeltaX);
            double angle = radians * (180 / Math.PI);
            double percent = (100 * angle) / GlobalVar.PriceFullAngle;
            return deltaY > 0.0 ? percent : -percent;
        }

        public void MakeWave(int a_CurIndex)
        {
            m_EasyTraderWaveManager.EasyTraderDataSet = m_EasyTraderDataSet;
            m_EasyTraderWaveManager.MakeWaveListFromFutOptChart(a_CurIndex + 1);
        }

        // 이 함수는 파동에 의해서 매도와 매수를 결정해 반환한다.
        // 퍼센트로 반환을 한다.
        public double GetWaveSignal(int a_CurIndex)
        {
            double signalVal = GlobalVar.SignalNone;

            if (m_EasyTraderWaveManager == null || m_EasyTraderDataSet == null)
                return 0;
            
            int index = Math.Min(a_CurIndex, GlobalVar.MaxDayIndex);
            EasyTrader.Wave.PriceWave curWave = m_EasyTraderWaveManager.GetCurWave(index);
            if (curWave == null)
                return 0;
            double deltaY = curWave.EndY - curWave.StartY;
            double deltaX = curWave.EndX - curWave.StartX;
            double ABSdeltaY = Math.Abs(deltaY) * GlobalVar.PricePerMin;
            double ABSdeltaX = Math.Abs(deltaX);
            double radians = Math.Atan2(ABSdeltaY, ABSdeltaX);
            double angle = radians * (180 / Math.PI);
            double percent = (100 * angle) / GlobalVar.PriceFullAngle;
            return deltaY > 0.0 ? percent : -percent;
        }

        public int GetForecastingInfo(ForecastingInfo a_Fore, string a_ColName, string a_RegType, int a_EndX, int a_MaxRange, bool a_AllowZero)
        {
            if (a_ColName == "" || a_EndX < 0 || a_MaxRange < 0 || a_Fore == null)
                return -1;
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return -1;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return -1;
            return Forecaster.GetForecastingInfo(a_Fore, curTable, a_ColName, a_RegType, a_EndX, a_MaxRange, a_AllowZero);
        }

        public int GetForecastingInfo(ForecastingInfo a_Fore, string a_ColName, string a_RegType, EasyTrader.Wave.PriceWave a_CurWave, bool a_AllowZero)
        {
            if (a_ColName == "" || a_Fore == null || a_CurWave == null)
                return -1;
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return -1;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return -1;
            return Forecaster.GetForecastingInfoBeginEnd(a_Fore, curTable, a_ColName, a_RegType, a_CurWave.StartX, a_CurWave.EndX, a_AllowZero);
        }


        public int GetForecastingInfoByBeginEnd(ForecastingInfo a_Fore, string a_ColName, string a_RegType, int a_StartX, int a_EndX, bool a_AllowZero)
        {
            if (a_ColName == "" || a_Fore == null || a_StartX < 0 || a_EndX < 0)
                return -1;
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return -1;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return -1;
            return Forecaster.GetForecastingInfoBeginEnd(a_Fore, curTable, a_ColName, a_RegType, a_StartX, a_EndX, a_AllowZero);
        }

        public int GetForecastingInfoByBeginEnd(ForecastingInfo a_Fore, string a_ColName1, string a_ColName2, string a_RegType, int a_StartX, int a_EndX)
        {
            if (a_ColName1 == "" || a_ColName2 == "" || a_Fore == null || a_StartX < 0 || a_EndX < 0)
                return -1;
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return -1;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return -1;
            return Forecaster.GetForecastingInfoBeginEnd(a_Fore, curTable, a_ColName1, a_ColName2, a_RegType, a_StartX, a_EndX);
        }

        public int GetForecastingInfo(ForecastingInfo a_Fore, string a_ColName, string a_RegType, int a_MaxRange, bool a_AllowZero)
        {
            if (a_ColName == "" || a_MaxRange < 0 || a_Fore == null)
                return -1;
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return -1;
            int rowCount = curTable.GetRowCount();
            if (rowCount < 2)
                return -1;
            return Forecaster.GetForecastingInfo(a_Fore, curTable, a_ColName, a_RegType, rowCount - 1, a_MaxRange, a_AllowZero);
        }

        public void ClearSignalWaveList()
        {
            m_SignalWaveList.Clear();
        }
        // 파동의 시작점에서 지표 마지막 값이 기준값을 지나 올라감
        public bool IsDayOpenCrossUp()
        {
            if (m_PriceList == null)
                return false;

            if (m_PriceList.Count == 0)
                return false;
            double dayOpenVal = m_PriceList[0].Y;
            double curVal = m_PriceList[m_PriceList.Count - 1].Y;

            if (curVal > dayOpenVal)
                return true;
            else
                return false;
        }

        public bool IsDayOpenCrossUp(PricePointList a_PriceList)
        {
            if (a_PriceList == null)
                return false;

            if (a_PriceList.Count == 0)
                return false;
            double dayOpenVal = a_PriceList[0].Y;
            double curVal = a_PriceList[a_PriceList.Count - 1].Y;

            if (curVal > dayOpenVal)
                return true;
            else
                return false;
        }

        public bool IsDayOpenCrossUp(PricePointList a_PriceList, EasyTrader.Wave.PriceWave a_CurWave)
        {
            if (a_PriceList == null)
                return false;

            if (a_PriceList.Count == 0)
                return false;
            double dayOpenVal = a_PriceList[0].Y;
            double curVal = a_CurWave.EndY;

            if (curVal > dayOpenVal)
                return true;
            else
                return false;
        }

        // 기준값을 지나 내려감
        public bool IsDayOpenCrossDown()
        {
            if (m_PriceList == null)
                return false;

            if (m_PriceList.Count == 0)
                return false;
            double dayOpenVal = m_PriceList[0].Y;
            double curVal = m_PriceList[m_PriceList.Count - 1].Y;

            if (curVal < dayOpenVal)
                return true;
            else
                return false;
        }

        public bool IsDayOpenCrossDown(PricePointList a_PriceList)
        {
            if (a_PriceList == null)
                return false;

            if (a_PriceList.Count == 0)
                return false;
            double dayOpenVal = a_PriceList[0].Y;
            double curVal = a_PriceList[a_PriceList.Count - 1].Y;

            if (curVal < dayOpenVal)
                return true;
            else
                return false;
        }

        public bool IsDayOpenCrossDown(PricePointList a_PriceList, EasyTrader.Wave.PriceWave a_CurWave)
        {
            if (a_PriceList == null || a_CurWave == null)
                return false;

            if (a_PriceList.Count == 0)
                return false;
            double dayOpenVal = a_PriceList[0].Y;
            double curVal = a_CurWave.EndY;

            if (curVal < dayOpenVal)
                return true;
            else
                return false;
        }
        
        // 파동에서 신호를 만든다.
        public void CreateWave(int a_DataCount)
        {
            // 파동 관리자가 없거나 데이터가 없으면 신호를 만들지 않는다.
            if (m_EasyTraderWaveManager == null || a_DataCount <= 0)
                return;
            // 먼저 파동을 현재 데이터 개수에 이르기까지 파동을 만든다.
            // 마지막 파동과 마지막 지점이 주어진 조건을 만족하는지 확인하여 신호를 만든다.
            m_EasyTraderWaveManager.MakeWaveListFromFutOptChart(a_DataCount);
        }

        public void MakeSignalWaveList(int a_CurIndex)
        {
            EasyTrader.Wave.PriceWave curSignalWave = FindSignalWave(a_CurIndex);
            AddSignalWave(curSignalWave);
        }

        private void AddSignalWave(EasyTrader.Wave.PriceWave a_CurWave)
        {
            int waveCount = m_SignalWaveList.Count;
            AdjustSignalWave(a_CurWave);
            if (waveCount <= 0)
            {
                m_SignalWaveList.Add(a_CurWave.Clone());
            }
            else
            {
                EasyTrader.Wave.PriceWave lastSignalWave = m_SignalWaveList[waveCount - 1];
                // 마지막 신호 파동과 방향이 같을 때에는 추가하지 않고 정보만 바꿔준다.
                if (a_CurWave.Slope == lastSignalWave.Slope)
                {
                    lastSignalWave.StartX = a_CurWave.StartX;
                    lastSignalWave.StartY = a_CurWave.StartY;
                    lastSignalWave.EndX = a_CurWave.EndX;
                    lastSignalWave.EndY = a_CurWave.EndY;
                    lastSignalWave.Slope = a_CurWave.Slope;
                    return;
                }
                // 방향이 다를 때는 새로운 기준파가 생긴것이므로 새로 추가를 해준다.
                else
                {
                    m_SignalWaveList.Add(a_CurWave.Clone());
                }
            }
        }

        // 신호 파동에 대한 XY 값 정리를 해준다.
        public void AdjustSignalWave(EasyTrader.Wave.PriceWave a_Wave)
        {
            if (a_Wave == null)
                return;

            int x1 = 0, x2 = 0;
            double y1 = 0.0, y2 = 0.0;
            if (a_Wave.StartX < a_Wave.EndX)
            {
                x1 = a_Wave.StartX;
                y1 = a_Wave.StartY;
                x2 = a_Wave.EndX;
                y2 = a_Wave.EndY;
            }
            else
            {
                x1 = a_Wave.EndX;
                y1 = a_Wave.EndY;
                x2 = a_Wave.StartX;
                y2 = a_Wave.StartY;
            }

            a_Wave.StartX = x1;
            a_Wave.StartY = y1;
            a_Wave.EndX = x2;
            a_Wave.EndY = y2;
            double deltaY = y2 - y1;
            if (deltaY > 0)
                a_Wave.Slope = GlobalVar.PriceUp;
            else if (deltaY < 0)
                a_Wave.Slope = GlobalVar.PriceDown;
            else
                a_Wave.Slope = GlobalVar.PriceFlat;
        }

        public EasyTrader.Wave.PriceWave FindArrangeWave(int a_Index)
        {
            PriceWaveList waveList = m_EasyTraderWaveManager.ArragedWaveList;
            if (waveList.Count == 0)
                return null;

            for (int i = 0; i < waveList.Count; i++)
            {
                EasyTrader.Wave.PriceWave wave = waveList[i];
                if (wave.StartX <= a_Index && a_Index < wave.EndX)
                    return wave;
            }

            return null;
        }
        private EasyTrader.Wave.PriceWave FindSignalWave(int a_CurIndex)
        {
            if (m_EasyTraderDataSet == null)
                return null;
            PriceWaveList waveList = m_EasyTraderWaveManager.ArragedWaveList;
            int count = waveList.Count;
            if (count == 0)
                return null;
            EasyTrader.DataSet.FutOptChartTable curTable = m_EasyTraderDataSet.GetFutOptChartTable();
            if (curTable == null)
                return null;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return null;
            if (a_CurIndex < 0)
                return null;
            if (a_CurIndex > rowCount - 1)
                a_CurIndex = rowCount - 1;

            //EasyTrader.Wave.PriceWave signalWave = new EasyTrader.Wave.PriceWave();

            int waveStartIndex = count - 2;
            if (waveStartIndex < 0)
                waveStartIndex = 0;

            EasyTrader.Wave.PriceWave wave = waveList[waveStartIndex];
            int startX = wave.EndX;
            if (startX > rowCount - 1)
                startX = rowCount - 1;
            DataRow row = curTable.Rows[startX];
            double high = Convert.ToDouble(row["고가"]);
            double low = Convert.ToDouble(row["저가"]);
            m_SignalWave.StartX = startX;
            m_SignalWave.EndX = startX;
            m_SignalWave.StartY = low;
            m_SignalWave.EndY = high;
            double deltaY = 0;

            for (int i = waveStartIndex; i >= 0; i--)
            {
                wave = waveList[i];
                int endX = wave.StartX;
                endX = Math.Max(wave.StartX - 10, 0);
                for (int j = startX; j >= endX; j--)
                {
                    row = curTable.Rows[j];
                    high = Convert.ToDouble(row["고가"]);
                    low = Convert.ToDouble(row["저가"]);
                    if (low < m_SignalWave.StartY)
                    {
                        m_SignalWave.StartY = low;
                        m_SignalWave.StartX = j;
                    }
                    if (high > m_SignalWave.EndY)
                    {
                        m_SignalWave.EndY = high;
                        m_SignalWave.EndX = j;
                    }
                }
                deltaY = m_SignalWave.Height();
                if (deltaY >= GlobalVar.SignalWaveHeight)
                {
                    int k = 0;
                    k = k + 1;
                    break;
                }
                startX = endX;
            }

            if (deltaY < GlobalVar.MinSignalWaveHeight)
                return null;
            else
                return m_SignalWave;
        }

        public void FindSignalWave(PriceWaveList a_WaveList, PricePointList a_PriceList)
        {
            if (a_WaveList == null || a_PriceList == null)
                return;
            if (a_WaveList.Count == 0 || a_PriceList.Count < 2)
                return;
            int waveCount = a_WaveList.Count;
            EasyTrader.Wave.PriceWave curWave = a_WaveList[waveCount - 1];
            if (curWave == null)
                return;
            EasyTrader.Wave.PriceWave signalWave = null;
            EasyTrader.Wave.PricePoint curPoint = a_PriceList[a_PriceList.Count - 1];
            if (curPoint == null)
                return;
            int signalWaveCount = m_SignalWaveList.Count;
            // 신호파동이 하나도 만들어지지 않았을 때
            if (signalWaveCount <= 0)
            {
                signalWave = new EasyTrader.Wave.PriceWave();
                signalWave.StartX = curWave.StartX;
                signalWave.StartY = curWave.StartY;
                signalWave.Slope = curWave.Slope;
                signalWave.EndX = curWave.EndX;
                signalWave.EndY = curWave.EndY;
                m_SignalWaveList.Add(signalWave);
            }
            else
            {
                // 현재 신호파동을 가져온다.
                EasyTrader.Wave.PriceWave curSignalWave = m_SignalWaveList[signalWaveCount - 1];
                // 현재 파동과 신호파동이 방향이 같을 때는 신호파동의 종점만 갱신해 준다.
                if (curSignalWave.Slope == curWave.Slope)
                {
                    curSignalWave.EndY = curWave.EndY;
                    curSignalWave.EndX = curPoint.X;
                }
                else // 신호파동과 현재 파동의 방향이 다를 때
                {
                    // 현재 신호 파동이 짧은 파동일 때
                    if (curSignalWave.Height() < GlobalVar.SignalMinWaveHeight)
                    {
                        // 파동의 개수가 3개이하일 때는 단파 방향 전환을 적극 고려한다.
                        if (waveCount <= 3)
                        {
                            if ((curWave.Slope == GlobalVar.PriceUp && IsDayOpenCrossUp(a_PriceList)) ||
                                (curWave.Slope == GlobalVar.PriceDown && IsDayOpenCrossDown(a_PriceList)))
                            {
                                curSignalWave.EndX = curPoint.X;
                                double endY = curSignalWave.EndY;
                                signalWave = new EasyTrader.Wave.PriceWave();
                                signalWave.StartX = curPoint.X;
                                signalWave.StartY = endY;
                                signalWave.Slope = curWave.Slope;
                                signalWave.EndX = curPoint.X;
                                signalWave.EndY = endY;
                                m_SignalWaveList.Add(signalWave);
                            }
                            else
                            {
                                curSignalWave.EndX = curPoint.X;
                            }
                        }
                        else
                        {
                            curSignalWave.EndX = curPoint.X;
                        }
                    }
                    else // 현재 신호 파동이 긴 파동일 대
                    {
                        double longHeight = curSignalWave.Height();
                        double shortHeight = curWave.Height();
                        double ratio = shortHeight / longHeight;
                        if (ratio < GlobalVar.SignalTransMinPercent)
                        {
                            curSignalWave.EndX = curPoint.X;
                        }
                        else
                        {
                            curSignalWave.EndX = curPoint.X;
                            double endY = curSignalWave.EndY;
                            signalWave = new EasyTrader.Wave.PriceWave();
                            signalWave.StartX = curPoint.X;
                            signalWave.StartY = endY;
                            signalWave.Slope = curWave.Slope;
                            signalWave.EndX = curPoint.X;
                            signalWave.EndY = endY;
                            m_SignalWaveList.Add(signalWave);
                        }
                    }
                }
            }
        }

        public int FindSignal(PriceWaveList a_WaveList, PricePointList a_PriceList)
        {
            int signalVal = GlobalVar.SignalNone;
            if (a_WaveList == null || a_PriceList == null)
                return signalVal;
            if (a_WaveList.Count == 0 || a_PriceList.Count < 2)
                return signalVal;
            int waveCount = a_WaveList.Count;
            EasyTrader.Wave.PriceWave curWave = a_WaveList[waveCount - 1];
            if (curWave == null)
                return signalVal;
            EasyTrader.Wave.PriceWave signalWave = null;
            EasyTrader.Signal.PriceSignal signal = null;
            EasyTrader.Wave.PricePoint curPoint = a_PriceList[a_PriceList.Count - 1];
            if (curPoint == null)
                return signalVal;
            int signalWaveCount = m_SignalWaveList.Count;
            // 신호파동이 하나도 만들어지지 않았을 때
            if (signalWaveCount <= 0)
            {
                signalWave = new EasyTrader.Wave.PriceWave();
                signalWave.StartX = curWave.StartX;
                signalWave.StartY = curWave.StartY;
                signalWave.Slope = curWave.Slope;
                signalWave.EndX = curWave.EndX;
                signalWave.EndY = curWave.EndY;
                m_SignalWaveList.Add(signalWave);
            }
            else
            {
                // 현재 신호파동을 가져온다.
                EasyTrader.Wave.PriceWave curSignalWave = m_SignalWaveList[signalWaveCount - 1];
                // 현재 파동과 신호파동이 방향이 같을 때는 신호파동의 종점만 갱신해 준다.
                if (curSignalWave.Slope == curWave.Slope)
                {
                    curSignalWave.EndY = curWave.EndY;
                    curSignalWave.EndX = curPoint.X;
                }
                else // 신호파동과 현재 파동의 방향이 다를 때
                {
                    // 현재 신호 파동이 짧은 파동일 때
                    if (curSignalWave.Height() < GlobalVar.SignalMinWaveHeight)
                    {
                        // 파동의 개수가 2개이하일 때는 단파 방향 전환을 적극 고려한다.
                        if (waveCount <= 2)
                        {
                            double longHeight = curSignalWave.Height();
                            double shortHeight = curWave.Height();
                            double ratio = shortHeight / longHeight;
                            if (ratio >= 0.5)
                            {
                                curSignalWave.EndX = curPoint.X;
                                double endY = curSignalWave.EndY;
                                signalWave = new EasyTrader.Wave.PriceWave();
                                signalWave.StartX = curPoint.X;
                                signalWave.StartY = endY;
                                signalWave.Slope = curWave.Slope;
                                signalWave.EndX = curPoint.X;
                                signalWave.EndY = endY;
                                m_SignalWaveList.Add(signalWave);

                                signal = new EasyTrader.Signal.PriceSignal();
                                signal.X = curPoint.X;
                                signal.Y = curPoint.Y;
                                signal.Time = Convert.ToInt32(curPoint.Time);
                                if (signalWave.Slope == GlobalVar.PriceUp)
                                    signal.Type = GlobalVar.SignalBuy;
                                else if (signalWave.Slope == GlobalVar.PriceDown)
                                    signal.Type = GlobalVar.SignalSell;
                                else
                                    signal.Type = GlobalVar.SignalNone;
                                m_PriceSignalList.Add(signal);
                                signalVal = signal.Type;
                            }
                            else
                            {
                                if ((curWave.Slope == GlobalVar.PriceUp && IsDayOpenCrossUp(a_PriceList)) ||
                                (curWave.Slope == GlobalVar.PriceDown && IsDayOpenCrossDown(a_PriceList)))
                                {
                                    curSignalWave.EndX = curPoint.X;
                                    double endY = curSignalWave.EndY;
                                    signalWave = new EasyTrader.Wave.PriceWave();
                                    signalWave.StartX = curPoint.X;
                                    signalWave.StartY = endY;
                                    signalWave.Slope = curWave.Slope;
                                    signalWave.EndX = curPoint.X;
                                    signalWave.EndY = endY;
                                    m_SignalWaveList.Add(signalWave);

                                    signal = new EasyTrader.Signal.PriceSignal();
                                    signal.X = curPoint.X;
                                    signal.Y = curPoint.Y;
                                    signal.Time = Convert.ToInt32(curPoint.Time);
                                    if (signalWave.Slope == GlobalVar.PriceUp)
                                        signal.Type = GlobalVar.SignalBuy;
                                    else if (signalWave.Slope == GlobalVar.PriceDown)
                                        signal.Type = GlobalVar.SignalSell;
                                    else
                                        signal.Type = GlobalVar.SignalNone;
                                    m_PriceSignalList.Add(signal);
                                    signalVal = signal.Type;
                                }
                                else
                                {
                                    curSignalWave.EndX = curPoint.X;
                                }
                            }
                        }
                        else
                        {
                            curSignalWave.EndX = curPoint.X;
                        }
                    }
                    else // 현재 신호 파동이 긴 파동일 대
                    {
                        double longHeight = curSignalWave.Height();
                        double shortHeight = curWave.Height();
                        double ratio = shortHeight / longHeight;
                        if (ratio < GlobalVar.SignalTransMinPercent)
                        {
                            curSignalWave.EndX = curPoint.X;
                        }
                        else
                        {
                            curSignalWave.EndX = curPoint.X;
                            double endY = curSignalWave.EndY;
                            signalWave = new EasyTrader.Wave.PriceWave();
                            signalWave.StartX = curPoint.X;
                            signalWave.StartY = endY;
                            signalWave.Slope = curWave.Slope;
                            signalWave.EndX = curPoint.X;
                            signalWave.EndY = endY;
                            m_SignalWaveList.Add(signalWave);

                            signal = new EasyTrader.Signal.PriceSignal();
                            signal.X = curPoint.X;
                            signal.Y = curPoint.Y;
                            signal.Time = Convert.ToInt32(curPoint.Time);
                            if (signalWave.Slope == GlobalVar.PriceUp)
                                signal.Type = GlobalVar.SignalBuy;
                            else if (signalWave.Slope == GlobalVar.PriceDown)
                                signal.Type = GlobalVar.SignalSell;
                            else
                                signal.Type = GlobalVar.SignalNone;
                            m_PriceSignalList.Add(signal);
                            signalVal = signal.Type;
                        }
                    }
                }
            }

            return signalVal;
        } // function

        public override int GetSignal(int a_DataCount)
        {
            if (a_DataCount <= 0)
                return GlobalVar.SignalNone;
            CreateWave(a_DataCount);
            // 정렬된 파동을 가져온다.
            PriceWaveList waveList = m_EasyTraderWaveManager.ArragedWaveList;
            PricePointList pointList = m_EasyTraderWaveManager.FirstPriceList;
            return FindSignal(waveList, pointList);
        }
    }
}
